#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/shm.h>


struct msgbuf {
        long mtype;       /* message type, must be > 0 */
        char mtext;    /* message data */
};

union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };

void Init_sem(int semid,int value){

	union semun tmp;
	tmp.val = value;
	if((semctl(semid,0,SETVAL,tmp)) == -1){
		
		perror("Init sem error");
		exit(-1);		
	}
}

int Del_sem(int semid){
	
	union semun tmp;
	if((semctl(semid,0,IPC_RMID,tmp)) == -1){
	
		perror("Del sem error");
		exit(-1);		
	}
	return 0;
}

void v_sem(int semid){

	struct sembuf sbuf;

	sbuf.sem_num = 0;        /* Operate on semaphore 0 */
        sbuf.sem_op = 1;         /* Wait for value to equal 0 */
        sbuf.sem_flg = SEM_UNDO;
	if(semop(semid,&sbuf,1) == -1){
		
		perror("V error why");
		exit(-1);
	}
}


void p_sem(int semid){

	struct sembuf sbuf;

	sbuf.sem_num = 0;        /* Operate on semaphore 0 */
        sbuf.sem_op = -1;         /* Wait for value to equal 0 */
        sbuf.sem_flg = SEM_UNDO;
	if(semop(semid,&sbuf,1) == -1){
		
		perror("P error why");
		exit(-1);
	}
}

int main(){

	key_t key;
	int semid;
	int shmid;
	int msqid;
	char *shmddr;
	struct msgbuf msg;

	printf("This is server:");
	fflush(stdout);

	if((key = ftok(".",'m')) < 0){
		
		perror("ftok error");
		exit(-1);
	}

	 if((shmid = shmget(key, 1024, IPC_CREAT|0666)) == -1){
	 	perror("Create Shared Memory Error");
		exit(-1);
	}

	shmddr = (char *)shmat(shmid, 0, 0);
	
	if(shmddr == (void*)-1){
		
		perror("Attach Shared Memory Error");
		exit(-1);
	}

	if((semid = semget(key,1,IPC_CREAT|0666)) == -1){
		
		perror("segmet error");
		exit(-1);
	}

	Init_sem(semid,1);

	if((msqid = msgget(key,IPC_CREAT|0777)) == -1){

                perror("msgget error");
                exit(-1);
        }


	while(1){
	
		msgrcv(msqid,&msg,1,888,0);
		if(msg.mtext == 'q'){
			break;
		}
		if(msg.mtext == 'r'){
			p_sem(semid);
			printf("%s\n",shmddr);
			v_sem(semid);
		}
	}

	shmdt(shmddr);
	shmctl(shmid,IPC_RMID,0);
	msgctl(msqid,IPC_RMID,NULL);
	Del_sem(semid);

	return 0;
}
